package fachada;

import queixa.Queixa;
import queixa.reps.IRepositorioQueixa;
import queixa.reps.RepositorioQueixa;
import queixa.state.Aberta;
import util.adapter.Adapter;
import excecoes.ObjetoInexistenteException;
import excecoes.ObjetoInvalidoException;
import excecoes.ObjetoJaExistenteException;
import excecoes.RepositorioException;
import excecoes.SituacaoException;
import fachada.state.Situacao;
import fachada.strategy.EstadoPrefeitura;
import fachada.strategy.Extra;
import fachada.strategy.Normal;
import guiasaude.Especialidade;
import guiasaude.Hospital;
import guiasaude.UnidadeSaude;
import guiasaude.reps.IRepositorioEspecialidade;
import guiasaude.reps.IRepositorioUnidadeSaude;
import guiasaude.reps.RepositorioEspecialidade;
import guiasaude.reps.RepositorioUnidadeSaude;

public class Fachada implements IFachada {

//	private RepositorioQueixaArray repQueixa;
//	private RepositorioUnidadeSaudeArray repUnidadeSaude;
//	private IRepositorioEspecialidade repEspecialidade;
	private IRepositorioQueixa repQueixa;
	private IRepositorioUnidadeSaude repUnidadeSaude;
	private IRepositorioEspecialidade repEspecialidade;

	public static final EstadoPrefeitura NORMAL = new Normal();
	public static final EstadoPrefeitura EXTRA = new Extra();
	private EstadoPrefeitura situacaoAtualPrefeitura = Fachada.NORMAL;

	private static String tipoRepositorio = "Array";
	
	public Fachada(String tipoRep) {
		
//		this.repQueixa = new RepositorioQueixaArray();
//		this.repUnidadeSaude = new RepositorioUnidadeSaudeArray();
//		this.repEspecialidade = RepositorioEspecialidade.getInstance();
				
		// Utilizando o Padrao Factory
		Fachada.setTipoRep(tipoRep);
		this.repQueixa = RepositorioQueixa.getInstance();
		this.repUnidadeSaude = RepositorioUnidadeSaude.getInstance();
		this.repEspecialidade = new RepositorioEspecialidade();
	}

	private static void setTipoRep(String tipoRep) {
		if (tipoRep != null) tipoRepositorio = tipoRep;
	}
	public static String getTipoRep() {
		return Fachada.tipoRepositorio;
	}
	
	/* (non-Javadoc)
	 * @see fachada.IFachada#consultarQueixa(int)
	 */
	public Queixa consultarQueixa(int codigo) throws RepositorioException,
			ObjetoInexistenteException {
		Queixa q = null;
		q = this.repQueixa.procura(codigo);
		return q;
	}

	/* (non-Javadoc)
	 * @see fachada.IFachada#fecharQueixa(queixa.Queixa, java.lang.String)
	 */
	public void fecharQueixa(Queixa queixa, String coment)
			throws RepositorioException, ObjetoInexistenteException,
			ObjetoInvalidoException, SituacaoException {
		queixa.fechar(coment);
		this.repQueixa.atualiza(queixa);
	}

	/* (non-Javadoc)
	 * @see fachada.IFachada#abrirQueixa(queixa.Queixa)
	 */
	public int abrirQueixa(Queixa queixa) throws RepositorioException,ObjetoInvalidoException,
			SituacaoException {
		
		queixa.abrir();
		
		return this.repQueixa.insere(queixa);
	}

	/* (non-Javadoc)
	 * @see fachada.IFachada#consultaEspecialidadeporUnidadeSaude(int)
	 */
	public IRepositorioEspecialidade consultaEspecialidadeporUnidadeSaude(
			int codigoUnidadeSaude) throws ObjetoInexistenteException,
			RepositorioException {

		UnidadeSaude us = this.repUnidadeSaude.procura(codigoUnidadeSaude);
		return us.getEspecialidades();
	}

	/* (non-Javadoc)
	 * @see fachada.IFachada#getUnidades()
	 */
	public IRepositorioUnidadeSaude getUnidades() {
		return repUnidadeSaude;
	}

	/* (non-Javadoc)
	 * @see fachada.IFachada#incluirEspecialidade(guiasaude.Especialidade)
	 */
	public void incluirEspecialidade(Especialidade esp)
			throws RepositorioException, ObjetoJaExistenteException,
			ObjetoInvalidoException {
		this.repEspecialidade.insere(esp);
	}

	/* (non-Javadoc)
	 * @see fachada.IFachada#incluirUnidadeSaude(guiasaude.UnidadeSaude)
	 */
	public void incluirUnidadeSaude(UnidadeSaude us)
			throws RepositorioException, ObjetoJaExistenteException,
			ObjetoInvalidoException {
		this.repUnidadeSaude.insere(us);
	}

	/* (non-Javadoc)
	 * @see fachada.IFachada#consultaEspecialidade(int)
	 */
	public Especialidade consultaEspecialidade(int codigo)
			throws RepositorioException, ObjetoInexistenteException {
		return this.repEspecialidade.procura(codigo);
	}

	/* (non-Javadoc)
	 * @see fachada.IFachada#consultaUnidadeSaude(int)
	 */
	public UnidadeSaude consultaUnidadeSaude(int codigo)
			throws RepositorioException, ObjetoInexistenteException {
		return this.repUnidadeSaude.procura(codigo);
	}

	/* (non-Javadoc)
	 * @see fachada.IFachada#calcularMediaMedicoPacienteDia(guiasaude.UnidadeSaude)
	 */
	public double calcularMediaMedicoPacienteDia(UnidadeSaude unidade) {
		if (unidade instanceof Hospital)
			return ((Hospital) unidade).medicos()
					/ ((Hospital) unidade).numPacientesDia();
		else
			// postosaude
			return ((Adapter) unidade).getAtendentes()
					/ ((Adapter) unidade).taxaDiaria();
	}

	/* (non-Javadoc)
	 * @see fachada.IFachada#consultaSituacaoQueixas()
	 */
	public Situacao consultaSituacaoQueixas() {

		// dependendo da situacao da prefeitura, o criterio de avaliacao muda
		// se normal, mais de 20% abertas eh ruim, mais de 10 eh regular
		// se extra, mais de 10% abertas eh ruim, mais de 5% eh regular
//		if (this.situacaoAtualPrefeitura == Fachada.NORMAL) {
//			if ((double) numeroQueixasAbertas() / repQueixa.size() > 0.2) {
//				return new Ruim();
//			} else {
//				if ((double) numeroQueixasAbertas() / repQueixa.size() > 0.1) {
//					return new Regular();
//				}
//			}
//		}
//		if (this.situacaoAtualPrefeitura == Fachada.EXTRA) {
//			if ((double) numeroQueixasAbertas() / repQueixa.size() > 0.1) {
//				return new Ruim();
//			} else {
//				if ((double) numeroQueixasAbertas() / repQueixa.size() > 0.05) {
//					return new Regular();
//				}
//			}
//		}
//		return new Otimo();
		
		Situacao s = this.situacaoAtualPrefeitura.getEstado(numeroQueixasAbertas(), repQueixa.size());
		return s;
	}

	/**
	 * metodo auxiliar para retornar o numero de queixas em aberto no sistema
	 * 
	 * @return
	 */
	private int numeroQueixasAbertas() {
		int contador = 0;
		for (int i = 0; i < repQueixa.size(); i++) {
			if (repQueixa.getElemento(i).getSituacao() instanceof Aberta)
				contador++;
		}

		return contador;
	}
}
